home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume10 / b+tree_mjr / part02 < prev    next >
Encoding:
Text File  |  1990-01-19  |  59.0 KB  |  2,186 lines

  1. Newsgroups: comp.sources.misc
  2. subject: v10i028: B+tree library, part02 of 5
  3. from: mjr@umiacs.UMD.EDU (Marcus J. Ranum)
  4. Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  5.  
  6. Posting-number: Volume 10, Issue 28
  7. Submitted-by: mjr@umiacs.UMD.EDU (Marcus J. Ranum)
  8. Archive-name: b+tree_mjr/part02
  9.  
  10. #! /bin/sh
  11. # This is a shell archive.  Remove anything before this line, then unpack
  12. # it by saving it into a file and typing "sh file".  To overwrite existing
  13. # files, type "sh file -c".  You can also feed this as standard input via
  14. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  15. # will see the following message at the end:
  16. #        "End of archive 2 (of 5)."
  17. # Contents:  b+tree/COPYRIGHT b+tree/btdbmlib/Makefile
  18. #   b+tree/btdbmlib/README b+tree/btdbmlib/stalloc.c
  19. #   b+tree/btdbmlib/stlinkb.c b+tree/btdbmlib/store.h
  20. #   b+tree/btdbmlib/strealloc.c b+tree/btlib/README
  21. #   b+tree/btlib/btconf.h b+tree/btlib/btdebug.c
  22. #   b+tree/btlib/btdelete.c b+tree/btlib/btload.c
  23. #   b+tree/btlib/btopen.c b+tree/btlib/btravrs.c b+tree/btlib/btree.h
  24. #   b+tree/utils/Makefile b+tree/utils/README b+tree/utils/btoptim.c
  25. # Wrapped by mjr@atreus on Fri Jan 19 10:34:58 1990
  26. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  27. if test -f 'b+tree/COPYRIGHT' -a "${1}" != "-c" ; then 
  28.   echo shar: Will not clobber existing file \"'b+tree/COPYRIGHT'\"
  29. else
  30. echo shar: Extracting \"'b+tree/COPYRIGHT'\" \(1688 characters\)
  31. sed "s/^X//" >'b+tree/COPYRIGHT' <<'END_OF_FILE'
  32. X
  33. X
  34. X         (C) Copyright, 1988, 1989 Marcus J. Ranum
  35. X                    All rights reserved
  36. X
  37. X
  38. XThis software, its documentation, and supporting  files  may
  39. Xbe  distributed and modified freely subject to the following
  40. Xconditions:
  41. X
  42. X1) None of the copyright headers in any of the files may  be
  43. Xaltered in any way.
  44. X
  45. X2) This software is not  to  be  incorporated  into  another
  46. Xsoftware package or operating system that is sold for a fee,
  47. Xor is "shareware", without  the  author's  written  consent,
  48. Xunless  the  source  code  to this software is included with
  49. Xthat package, or a notice  is  included  stating  that  this
  50. Xsoftware is available without a fee, who wrote it, and where
  51. Xto look for it.
  52. X
  53. X3) This software  may  not  be  distributed  in  binary-only
  54. Xformat,  unless  a  notice  is  included  stating  that this
  55. Xsoftware is available without a fee, and where to  look  for
  56. Xit.
  57. X
  58. X4) This software may not be redistributed in any manner that
  59. Xincludes  a  handling  charge,  without the author's written
  60. Xconsent.
  61. X
  62. X5) This  software  may  not  be  redistributed  without  its
  63. Xdocumentation  and  supporting  files. 
  64. X
  65. X
  66. XUsers are encouraged to modify this software and improve it,
  67. Xand to share those improvements with others. If you feel you
  68. Xhave improved it, please contact the author, if you want  to
  69. Xshare your improvements. Please inform the author of bugs or
  70. Xbug fixes.
  71. X
  72. X
  73. XThe author assumes no liability for the  use  or  misuse  of
  74. Xthis software, and makes no claims as to its suitability for
  75. Xany  purpose.  Do  not  take  internally.  See  a  physician
  76. Ximmediately if accidentally ingested.
  77. X
  78. X
  79. XMarcus J. Ranum
  80. X3018 Guilford Ave
  81. XBaltimore, Md 21218
  82. X
  83. X
  84. X                     Dec 19, 1989
  85. END_OF_FILE
  86. if test 1688 -ne `wc -c <'b+tree/COPYRIGHT'`; then
  87.     echo shar: \"'b+tree/COPYRIGHT'\" unpacked with wrong size!
  88. fi
  89. # end of 'b+tree/COPYRIGHT'
  90. fi
  91. if test -f 'b+tree/btdbmlib/Makefile' -a "${1}" != "-c" ; then 
  92.   echo shar: Will not clobber existing file \"'b+tree/btdbmlib/Makefile'\"
  93. else
  94. echo shar: Extracting \"'b+tree/btdbmlib/Makefile'\" \(1863 characters\)
  95. sed "s/^X//" >'b+tree/btdbmlib/Makefile' <<'END_OF_FILE'
  96. X#
  97. X#
  98. X#/*
  99. X#         (C) Copyright, 1988, 1989 Marcus J. Ranum
  100. X#                    All rights reserved
  101. X#
  102. X#
  103. X#          This software, its documentation,  and  supporting
  104. X#          files  are  copyrighted  material  and may only be
  105. X#          distributed in accordance with the terms listed in
  106. X#          the COPYRIGHT document.
  107. X#*/
  108. X#
  109. X# $Header: /atreus/mjr/hacks/btree/btdbmlib/RCS/Makefile,v 1.1 89/10/24 10:09:23 mjr Rel $
  110. X#
  111. X
  112. XBTHDRDIR=../btlib
  113. XDBHDRDIR=.
  114. X
  115. X# compiler to use
  116. XCC= cc
  117. X
  118. X#CFLAGS = -I$(BTHDRDIR) -I$(DBHDRDIR) -g
  119. X#CFLAGS = -I$(BTHDRDIR) -I$(DBHDRDIR) -p
  120. XCFLAGS = -I$(BTHDRDIR) -I$(DBHDRDIR) -O
  121. X
  122. XLDFLAGS= -g
  123. X
  124. X# where to build the library. must be set in testrack/Makefile
  125. X# if you change it from here.
  126. XLIBDIR=..
  127. XLIB=    $(LIBDIR)/libbtdbm.a
  128. X
  129. XCFILES=    btdbmclose.c \
  130. X    btdbmdelete.c \
  131. X    btdbmfetch.c \
  132. X    btdbmfirstkey.c \
  133. X    btdbmnextkey.c \
  134. X    btdbmopen.c \
  135. X    btdbmstore.c \
  136. X    stalloc.c \
  137. X    stclose.c \
  138. X    stcopy.c \
  139. X    stdecref.c \
  140. X    sterrs.c \
  141. X    stfree.c \
  142. X    stgethed.c \
  143. X    stincref.c \
  144. X    stlinka.c \
  145. X    stlinkb.c \
  146. X    stopen.c \
  147. X    stputhed.c \
  148. X    stread.c \
  149. X    strealloc.c \
  150. X    streallocbuf.c \
  151. X    stunlink.c \
  152. X    stwrite.c \
  153. X    stwsuper.c
  154. X
  155. XHFILES=    btdbm.h \
  156. X    stoconf.h \
  157. X    store.h \
  158. X    stointern.h
  159. X
  160. XOFILES=    btdbmclose.o \
  161. X    btdbmdelete.o \
  162. X    btdbmfetch.o \
  163. X    btdbmfirstkey.o \
  164. X    btdbmnextkey.o \
  165. X    btdbmopen.o \
  166. X    btdbmstore.o \
  167. X    stalloc.o \
  168. X    stclose.o \
  169. X    stcopy.o \
  170. X    stdecref.o \
  171. X    sterrs.o \
  172. X    stfree.o \
  173. X    stgethed.o \
  174. X    stincref.o \
  175. X    stlinka.o \
  176. X    stlinkb.o \
  177. X    stopen.o \
  178. X    stputhed.o \
  179. X    stread.o \
  180. X    strealloc.o \
  181. X    streallocbuf.o \
  182. X    stunlink.o \
  183. X    stwrite.o \
  184. X    stwsuper.o
  185. X
  186. XFILES=    $(CFILES) \
  187. X    $(HFILES) \
  188. X    README \
  189. X    Makefile
  190. X
  191. X$(LIB):    $(OFILES) 
  192. X    ar crv $(LIB) $(OFILES)
  193. X    ranlib $(LIB)
  194. X
  195. X$(OFILES): $(HFILES)
  196. X
  197. Xclean:
  198. X    rm -f *.o $(LIB) core tags rectest
  199. X
  200. Xci:
  201. X    ci -u $(FILES) < /dev/null
  202. X
  203. Xtags:
  204. X    ctags $(CFILES)
  205. X
  206. Xlint:    $(CFILES)
  207. X    lint -I$(BTHDRDIR) -I$(DBHDRDIR) -u $(CFILES) | sed '/pointer alignment/d'
  208. X
  209. END_OF_FILE
  210. if test 1863 -ne `wc -c <'b+tree/btdbmlib/Makefile'`; then
  211.     echo shar: \"'b+tree/btdbmlib/Makefile'\" unpacked with wrong size!
  212. fi
  213. # end of 'b+tree/btdbmlib/Makefile'
  214. fi
  215. if test -f 'b+tree/btdbmlib/README' -a "${1}" != "-c" ; then 
  216.   echo shar: Will not clobber existing file \"'b+tree/btdbmlib/README'\"
  217. else
  218. echo shar: Extracting \"'b+tree/btdbmlib/README'\" \(2690 characters\)
  219. sed "s/^X//" >'b+tree/btdbmlib/README' <<'END_OF_FILE'
  220. X
  221. X
  222. X/*
  223. X         (C) Copyright, 1988, 1989 Marcus J. Ranum
  224. X                    All rights reserved
  225. X
  226. X
  227. X          This software, its documentation,  and  supporting
  228. X          files  are  copyrighted  material  and may only be
  229. X          distributed in accordance with the terms listed in
  230. X          the COPYRIGHT document.
  231. X*/
  232. X
  233. X
  234. X    A few words about the arrangement of these modules::
  235. X
  236. XContents::
  237. XMakefile    - obvious.
  238. XREADME        - obvious.
  239. Xbtdbm.h        - header for btree-based dbm clone.
  240. Xbtdbmclose.c    - close function for btree-based dbm clone.
  241. Xbtdbmdelete.c    - delete function.
  242. Xbtdbmfetch.c    - fetch function.
  243. Xbtdbmfirstkey.c    - first key function.
  244. Xbtdbmnextkey.c    - key traversal function.
  245. Xbtdbmopen.c    - open function.
  246. Xbtdbmstore.c    - store function.
  247. Xstalloc.c    - storage allocation function.
  248. Xstclose.c    - storage file close function.
  249. Xstcopy.c    - storage file record copy/duplication function.
  250. Xstdecref.c    - storage file record reference count decrement fnction.
  251. Xsterrs.c    - storage file error strings file, and perror functions.
  252. Xstfree.c    - storage file free list manager. cryptic.
  253. Xstgethed.c    - storage file record header reader.
  254. Xstincref.c    - storage file record reference count increment fnction.
  255. Xstlinka.c    - storage file linked-list management "link after" function.
  256. Xstlinkb.c    - storage file linked-list management "link before" function.
  257. Xstoconf.h    - configuration information for storage file library.
  258. Xstointern.h    - internal macros for storage file library. not user level.
  259. Xstopen.c    - storage file opening/initialization function.
  260. Xstore.h        - main header for storage file library.
  261. Xstputhed.c    - storage file record header updater.
  262. Xstread.c    - storage file "read-like" function.
  263. Xstrealloc.c    - storage file record reallocation/copy function.
  264. Xstunlink.c    - storage file linked-list management unlink function.
  265. Xstwrite.c    - storage file "write-like" function.
  266. Xstwsuper.c    - storage file super-block updater function.
  267. X
  268. XNotes:
  269. X    There is some sleazy semi-optimization in the write/read routines,
  270. Xsince the header is read before the read or write, we know we don't have to
  271. Xre-seek before we actually do the read. This saves us a seek, so we do it,
  272. Xthough if the layout of the record headers changes, things will get evil.
  273. X
  274. X    For a detailed description of how the free list is managed, see
  275. Xstfree.c
  276. X
  277. X
  278. XTo Do:
  279. X1) Possibly add some form of record header caching. The current way makes
  280. Xtoo many system calls (about 4 per operation).
  281. X
  282. X2) Possibly add some form of file seek caching as well. Storing the location
  283. Xof the file pointer might save a few system calls.
  284. X
  285. X3) improve the btdbm library to use linked lists for multiple records with
  286. Xthe same key.
  287. X
  288. X4) improve the btdbm library to use more of the b+tree functionality.
  289. X
  290. X--mjr();
  291. END_OF_FILE
  292. if test 2690 -ne `wc -c <'b+tree/btdbmlib/README'`; then
  293.     echo shar: \"'b+tree/btdbmlib/README'\" unpacked with wrong size!
  294. fi
  295. # end of 'b+tree/btdbmlib/README'
  296. fi
  297. if test -f 'b+tree/btdbmlib/stalloc.c' -a "${1}" != "-c" ; then 
  298.   echo shar: Will not clobber existing file \"'b+tree/btdbmlib/stalloc.c'\"
  299. else
  300. echo shar: Extracting \"'b+tree/btdbmlib/stalloc.c'\" \(3466 characters\)
  301. sed "s/^X//" >'b+tree/btdbmlib/stalloc.c' <<'END_OF_FILE'
  302. X#include    <sys/types.h>
  303. X#include    "stoconf.h"
  304. X#include    "store.h"
  305. X#include    "stointern.h"
  306. X
  307. X
  308. X/*
  309. X         (C) Copyright, 1988, 1989 Marcus J. Ranum
  310. X                    All rights reserved
  311. X
  312. X
  313. X          This software, its documentation,  and  supporting
  314. X          files  are  copyrighted  material  and may only be
  315. X          distributed in accordance with the terms listed in
  316. X          the COPYRIGHT document.
  317. X*/
  318. X
  319. X
  320. X#ifndef    lint
  321. Xstatic char *rcsid = "$Header: /atreus/mjr/hacks/btree/btdbmlib/RCS/stalloc.c,v 1.1 89/10/24 10:09:12 mjr Rel $";
  322. X#endif
  323. X
  324. X/*
  325. X    storage allocation for the store library. allocation is performed
  326. X    as follows:
  327. X    1) if there is a free header list, read it sequentially and take
  328. X    the first fit.
  329. X        a)if the first fitting record is bigger than some compiled-in
  330. X        value, it is split into 2 subrecords, and the left-over
  331. X        is placed back into the free list. 
  332. X        b)if the first fitting record is not large enough to split
  333. X        without excessive fragmentation, return the whole thing
  334. X        and assume the user will be happy.
  335. X    2) if there is no free header list, allocate a new record chunk
  336. X    from the end-of-file and initialize it as empty.
  337. X
  338. X    the free header list is stored as a record, and is accessed and
  339. X    updated by library routines. it's somewhat self-referential, but
  340. X    works nicely. the only disadvantage of this approach is that it
  341. X    probably does more seeks than it should in an ideal world.
  342. X*/
  343. X
  344. X
  345. Xsto_ptr
  346. Xstore_alloc(r,bytes)
  347. XSTORE    *r;
  348. Xint        bytes;
  349. X{
  350. X    sto_ptr    ret = STO_NULL;
  351. X    struct    sto_hdr    rbuf;
  352. X
  353. X    if(bytes <= 0)
  354. X        return(STO_NULL);
  355. X
  356. X    if(r->sblk.free != STO_NULL) {
  357. X        struct    sto_freeent    fry;
  358. X        struct    sto_freeent    *freep;
  359. X        int    byt;
  360. X        off_t    currof;
  361. X        int    ismore;
  362. X        int    fcnt;
  363. X        int    junk;
  364. X
  365. X        currof = (off_t)(2 * sizeof(long));
  366. X
  367. X        while(1) {
  368. X
  369. X            ismore = store_read(r,r->sblk.free,currof,store_buffer(r),store_bufsiz(r),&byt);
  370. X            if(ismore == STO_ERR)
  371. X                return(STO_ERR);
  372. X
  373. X            if(currof == 0L) {
  374. X                freep = STO_FREEBUF(store_buffer(r));
  375. X                fcnt = ((byt - (2 * sizeof(off_t))) / STO_FSIZ); 
  376. X            } else {
  377. X                freep = (struct sto_freeent *)store_buffer(r);
  378. X                fcnt = byt / STO_FSIZ; 
  379. X            }
  380. X
  381. X            currof += (off_t)byt;
  382. X
  383. X            for(junk = 0; junk < fcnt; junk++) {
  384. X                if(bytes <= freep->size) {
  385. X
  386. X                    /* allocate it */
  387. X                    ret = freep->addr;
  388. X
  389. X                    /* if the block is big enough, split */                        /* it into a record of the desired */                        /* size and one consisting of the */
  390. X                    /* left-overs. if the size of the */
  391. X                    /* table scraps is small, just give */
  392. X                    /* the customer a bit extra */
  393. X                    if(freep->size - bytes >= STO_SPLITSIZ) {
  394. X                        fry.addr = freep->addr + STO_HSIZ + bytes;
  395. X                        
  396. X                        fry.size = freep->size - (2 * STO_HSIZ) - bytes;
  397. X                        rbuf.size = bytes; 
  398. X                    } else {
  399. X                        fry.addr = STO_NULL;
  400. X                        fry.size = 0;
  401. X                        rbuf.size = freep->size; 
  402. X                    }
  403. X
  404. X                    if(store_write(r,r->sblk.free,(off_t)(2 * sizeof(off_t) + (junk * STO_FSIZ)),(unsigned char *)&fry,STO_FSIZ) == STO_ERR)
  405. X                        return(STO_NULL);
  406. X
  407. X                    /* duh, break out of the loop */
  408. X                    junk = fcnt + 1;
  409. X                }
  410. X                freep++;
  411. X            }
  412. X            if(ismore != STO_MORE)
  413. X                break;
  414. X        }
  415. X        
  416. X    }
  417. X
  418. X    if(ret == STO_NULL) {
  419. X        ret = r->sblk.high;
  420. X        r->sblk.high += bytes + STO_HSIZ;
  421. X        rbuf.size = bytes; 
  422. X        rbuf.used = 0; 
  423. X        rbuf.refs = 1; 
  424. X        rbuf.next = rbuf.prev = STO_NULL;
  425. X        if(store_wsuper(r) != STO_OK)
  426. X            return(STO_NULL);
  427. X    }
  428. X
  429. X    rbuf.magic = STO_DFLTMAGIC; 
  430. X    rbuf.used = 0; 
  431. X    rbuf.refs = 1; 
  432. X    rbuf.next = rbuf.prev = STO_NULL;
  433. X
  434. X    if(store_puthdr(r,ret,&rbuf) == STO_ERR)
  435. X        return(STO_NULL);
  436. X
  437. X    return(ret);
  438. X}
  439. END_OF_FILE
  440. if test 3466 -ne `wc -c <'b+tree/btdbmlib/stalloc.c'`; then
  441.     echo shar: \"'b+tree/btdbmlib/stalloc.c'\" unpacked with wrong size!
  442. fi
  443. # end of 'b+tree/btdbmlib/stalloc.c'
  444. fi
  445. if test -f 'b+tree/btdbmlib/stlinkb.c' -a "${1}" != "-c" ; then 
  446.   echo shar: Will not clobber existing file \"'b+tree/btdbmlib/stlinkb.c'\"
  447. else
  448. echo shar: Extracting \"'b+tree/btdbmlib/stlinkb.c'\" \(1610 characters\)
  449. sed "s/^X//" >'b+tree/btdbmlib/stlinkb.c' <<'END_OF_FILE'
  450. X#include    <sys/types.h>
  451. X#include    "stoconf.h"
  452. X#include    "store.h"
  453. X
  454. X
  455. X/*
  456. X         (C) Copyright, 1988, 1989 Marcus J. Ranum
  457. X                    All rights reserved
  458. X
  459. X
  460. X          This software, its documentation,  and  supporting
  461. X          files  are  copyrighted  material  and may only be
  462. X          distributed in accordance with the terms listed in
  463. X          the COPYRIGHT document.
  464. X*/
  465. X
  466. X
  467. X#ifndef    lint
  468. Xstatic char *rcsid = "$Header: /atreus/mjr/hacks/btree/btdbmlib/RCS/stlinkb.c,v 1.1 89/10/24 10:09:16 mjr Rel $";
  469. X#endif
  470. X
  471. X/*
  472. X    manipulate the link pointers of a header to link the record numbered
  473. X    'pred' BEFORE the record numbered 'victim'. Note that no attempt is
  474. X    made to UNLINK the victim if it is already linked into a list.
  475. X    that must be controlled at a higher level, or we get into a kind
  476. X    of recursive linking and unlinking loop and never return.
  477. X*/
  478. X
  479. Xstore_linkbefore(r,victim,next)
  480. XSTORE    *r;
  481. Xsto_ptr        victim;
  482. Xsto_ptr        next;
  483. X{
  484. X    struct    sto_hdr     nbuf;
  485. X    struct    sto_hdr     pbuf;
  486. X    struct    sto_hdr     vbuf;
  487. X    char    pnul = 0;
  488. X
  489. X    if(next == STO_NULL) {
  490. X        store_errno(r) = STO_NOREC;
  491. X        return(STO_ERR);
  492. X    }
  493. X
  494. X    if(store_gethdr(r,victim,&vbuf) == STO_ERR || store_gethdr(r,next,&nbuf) == STO_ERR)
  495. X        return(STO_ERR);
  496. X
  497. X    if(nbuf.prev != STO_NULL)
  498. X        pnul++;
  499. X
  500. X    if(pnul && store_gethdr(r,nbuf.prev,&pbuf) == STO_ERR)
  501. X        return(STO_ERR);
  502. X
  503. X    if(pnul)
  504. X        pbuf.next = victim;
  505. X    vbuf.next = next;
  506. X    vbuf.prev = nbuf.prev;
  507. X    nbuf.prev = victim;
  508. X
  509. X    if(store_puthdr(r,victim,&vbuf) == STO_ERR || store_puthdr(r,next,&nbuf) == STO_ERR)
  510. X        return(STO_ERR);
  511. X
  512. X    if(pnul && store_puthdr(r,vbuf.prev,&pbuf) == STO_ERR)
  513. X        return(STO_ERR);
  514. X
  515. X    return(STO_OK);
  516. X}
  517. END_OF_FILE
  518. if test 1610 -ne `wc -c <'b+tree/btdbmlib/stlinkb.c'`; then
  519.     echo shar: \"'b+tree/btdbmlib/stlinkb.c'\" unpacked with wrong size!
  520. fi
  521. # end of 'b+tree/btdbmlib/stlinkb.c'
  522. fi
  523. if test -f 'b+tree/btdbmlib/store.h' -a "${1}" != "-c" ; then 
  524.   echo shar: Will not clobber existing file \"'b+tree/btdbmlib/store.h'\"
  525. else
  526. echo shar: Extracting \"'b+tree/btdbmlib/store.h'\" \(1913 characters\)
  527. sed "s/^X//" >'b+tree/btdbmlib/store.h' <<'END_OF_FILE'
  528. X#ifndef    _DEF_STO_H
  529. X
  530. X/*
  531. X         (C) Copyright, 1988, 1989 Marcus J. Ranum
  532. X                    All rights reserved
  533. X
  534. X
  535. X          This software, its documentation,  and  supporting
  536. X          files  are  copyrighted  material  and may only be
  537. X          distributed in accordance with the terms listed in
  538. X          the COPYRIGHT document.
  539. X*/
  540. X
  541. X
  542. X/*
  543. X    $Header: /atreus/mjr/hacks/btree/btdbmlib/RCS/store.h,v 1.1 89/10/24 10:09:20 mjr Rel $
  544. X*/
  545. X
  546. X#define    STO_NULL    -1L
  547. X
  548. X#define    STO_OK        0
  549. X#define    STO_ERR        1
  550. X#define    STO_MORE    2
  551. X
  552. X/* STARTING size of the store file internal buffer */
  553. X/* this is also the size of the initial free list block */
  554. X#define    STO_BUFSIZ    1024
  555. X
  556. Xtypedef    off_t    sto_ptr;
  557. X
  558. X/* a record header. one before each record in the file */
  559. Xstruct    sto_hdr {
  560. X    off_t    magic;
  561. X    int    size;
  562. X    int    used;
  563. X    int    refs;
  564. X    sto_ptr    next;
  565. X    sto_ptr    prev;
  566. X};
  567. X
  568. X/* store file super block */
  569. Xstruct    sto_sb {
  570. X    off_t    magic;
  571. X    off_t    high;
  572. X    sto_ptr    free;
  573. X    sto_ptr    label;
  574. X};
  575. X
  576. Xstruct    store_hand {
  577. X    int        fd;
  578. X    int        errno;
  579. X    sto_ptr        currec;        /* current record */
  580. X    sto_ptr        curlst;        /* current list head */
  581. X    struct        sto_sb    sblk;
  582. X    int        bufsiz;    /* buffer size */
  583. X    unsigned    char    *buf;    /* general porpoise buffer */
  584. X                    /* this buffer may "stretch" to */
  585. X                    /* accomodate data */
  586. X};
  587. X#define    STORE struct store_hand
  588. X
  589. X/* pseudo-functions */
  590. X#define    store_errno(r)    (r->errno)
  591. X#define    store_clearerr(r)        (r->errno = STO_NOERROR)
  592. X#define    store_fileno(r)    (r->fd)
  593. X#define    store_buffer(r)    (r->buf)
  594. X#define    store_bufsiz(r)    (r->bufsiz)
  595. X#define    store_currec(r)    (r->currec)
  596. X#define    store_label(r)    (r->sblk.label)
  597. X
  598. X/* forward decls */
  599. Xextern    STORE        *store_open();
  600. Xextern    sto_ptr        store_alloc();
  601. Xextern    sto_ptr        store_realloc();
  602. Xextern    void        store_perror();
  603. X
  604. X/* error codes and messages */
  605. Xextern    char    *sto_errs[];
  606. X
  607. X/* error constants */
  608. X#define    STO_NOERROR    0
  609. X#define    STO_BADHDR    1
  610. X#define    STO_IOERR    2
  611. X#define    STO_NOREC    3
  612. X#define    STO_TOOSMALL    4
  613. X
  614. X#define    _DEF_STO_H
  615. X#endif
  616. END_OF_FILE
  617. if test 1913 -ne `wc -c <'b+tree/btdbmlib/store.h'`; then
  618.     echo shar: \"'b+tree/btdbmlib/store.h'\" unpacked with wrong size!
  619. fi
  620. # end of 'b+tree/btdbmlib/store.h'
  621. fi
  622. if test -f 'b+tree/btdbmlib/strealloc.c' -a "${1}" != "-c" ; then 
  623.   echo shar: Will not clobber existing file \"'b+tree/btdbmlib/strealloc.c'\"
  624. else
  625. echo shar: Extracting \"'b+tree/btdbmlib/strealloc.c'\" \(1870 characters\)
  626. sed "s/^X//" >'b+tree/btdbmlib/strealloc.c' <<'END_OF_FILE'
  627. X#include    <sys/types.h>
  628. X#include    "stoconf.h"
  629. X#include    "store.h"
  630. X
  631. X
  632. X/*
  633. X         (C) Copyright, 1988, 1989 Marcus J. Ranum
  634. X                    All rights reserved
  635. X
  636. X
  637. X          This software, its documentation,  and  supporting
  638. X          files  are  copyrighted  material  and may only be
  639. X          distributed in accordance with the terms listed in
  640. X          the COPYRIGHT document.
  641. X*/
  642. X
  643. X
  644. X#ifndef    lint
  645. Xstatic char *rcsid = "$Header: /atreus/mjr/hacks/btree/btdbmlib/RCS/strealloc.c,v 1.1 89/10/24 10:09:17 mjr Rel $";
  646. X#endif
  647. X
  648. X/*
  649. X    record reallocator. this has to do a lot of ugly stuff because of
  650. X    the linked-list management. first it remembers the sibs of a record,
  651. X    allocates a new one, copies the old one into it, frees the old one,
  652. X    patches links and references and returns.
  653. X*/
  654. X
  655. Xsto_ptr
  656. Xstore_realloc(r,rec,bytes)
  657. XSTORE        *r;
  658. Xsto_ptr        rec;
  659. Xint        bytes;
  660. X{
  661. X    sto_ptr    ret;
  662. X    struct    sto_hdr    rbuf;
  663. X    struct    sto_hdr    nbuf;
  664. X
  665. X    /* remember this so we can patch any links that existed */
  666. X    if(store_gethdr(r,rec,&rbuf) == STO_ERR)
  667. X        return(STO_ERR);
  668. X
  669. X    ret = store_alloc(r,bytes);
  670. X    if(ret == STO_NULL)
  671. X        return(STO_NULL);
  672. X
  673. X    if(store_copy(r,rec,ret) == STO_ERR)
  674. X        return(STO_NULL);
  675. X
  676. X    if(store_free(r,rec) == STO_ERR)
  677. X        return(STO_NULL);
  678. X
  679. X    /* re-establish next links */
  680. X    if(rbuf.next != STO_NULL) {
  681. X        if(store_gethdr(r,rbuf.next,&nbuf) == STO_ERR)
  682. X            return(STO_ERR);
  683. X        nbuf.prev = ret;
  684. X        if(store_puthdr(r,rbuf.next,&nbuf) == STO_ERR)
  685. X            return(STO_ERR);
  686. X    }
  687. X
  688. X    /* re-establish prev links */
  689. X    if(rbuf.prev != STO_NULL) {
  690. X        if(store_gethdr(r,rbuf.prev,&nbuf) == STO_ERR)
  691. X            return(STO_ERR);
  692. X        nbuf.next = ret;
  693. X        if(store_puthdr(r,rbuf.prev,&nbuf) == STO_ERR)
  694. X            return(STO_ERR);
  695. X    }
  696. X
  697. X    if(store_gethdr(r,ret,&nbuf) == STO_ERR)
  698. X        return(STO_ERR);
  699. X
  700. X    nbuf.refs = rbuf.refs;
  701. X    nbuf.next = rbuf.next;
  702. X    nbuf.prev = rbuf.prev;
  703. X
  704. X    if(store_puthdr(r,ret,&nbuf) == STO_ERR)
  705. X        return(STO_ERR);
  706. X    return(ret);
  707. X}
  708. END_OF_FILE
  709. if test 1870 -ne `wc -c <'b+tree/btdbmlib/strealloc.c'`; then
  710.     echo shar: \"'b+tree/btdbmlib/strealloc.c'\" unpacked with wrong size!
  711. fi
  712. # end of 'b+tree/btdbmlib/strealloc.c'
  713. fi
  714. if test -f 'b+tree/btlib/README' -a "${1}" != "-c" ; then 
  715.   echo shar: Will not clobber existing file \"'b+tree/btlib/README'\"
  716. else
  717. echo shar: Extracting \"'b+tree/btlib/README'\" \(3983 characters\)
  718. sed "s/^X//" >'b+tree/btlib/README' <<'END_OF_FILE'
  719. X
  720. X
  721. X/*
  722. X         (C) Copyright, 1988, 1989 Marcus J. Ranum
  723. X                    All rights reserved
  724. X
  725. X
  726. X          This software, its documentation,  and  supporting
  727. X          files  are  copyrighted  material  and may only be
  728. X          distributed in accordance with the terms listed in
  729. X          the COPYRIGHT document.
  730. X*/
  731. X
  732. XTO COMPILE::
  733. X    edit btconf.h as necessary to reflect your system/preferences.
  734. X    edit Makefile to fix any necessary flags.
  735. X
  736. XTO INSTALL::
  737. X    only btree.h and the library need to be placed in user-accessible
  738. X    locations.
  739. X
  740. XTO TEST::
  741. X    build the library and check out the testing functions in ../utils.
  742. X    if there is a catastrophic failure, you're on your own.
  743. X
  744. XContents::
  745. Xbtree.h        - needed by anything using the btree code. defines various
  746. X        constants and macros, as well as forward declarations.
  747. Xbtconf.h    - put system specific configuration stuff here. this file
  748. X        contains compile-time options settings and system macros.
  749. Xbtintern.h    - NEVER include this in user level code unless you know
  750. X        bloody well what you're about. this file contains the
  751. X        internal page structures and mystical secret stuff that
  752. X        should never need to be edited.
  753. Xbtclose.c    - function to close a btree.
  754. Xbtdelete.c    - function to delete a key from a btree.
  755. Xbterrors.c    - error strings and bt_perror().
  756. Xbtfind.c    - function to locate a key in a btree.
  757. Xbtgoto.c    - function to go to first/last key of btree.
  758. Xbtinsert.c    - insert function.
  759. Xbtio.c        - cache manipulation routines, also functions for syncing
  760. X        buffers, writing superblocks, and allocating and freeing
  761. X        new pages.
  762. Xbtlabel.c    - functions for manipulating a label hidden in free space
  763. X        between first page and the end of the superblock.
  764. Xbtload.c    - function for optimal load of reverse sorted keys.
  765. Xbtopen.c    - simple btree opening function that doesn't provide much
  766. X        in the way of options.
  767. Xbtoopen.c    - btree opening function that provides access to every
  768. X        option supported by the library. uses varargs and will
  769. X        not compile on machines without varargs.
  770. Xbtpage1.c    - first half of the internal page manipulation routines.
  771. X        contains page search functions, page insert, and page
  772. X        split.
  773. Xbtpage2.c    - second half of the internal page manipulation routines.
  774. X        contains page delete function, and a function to grab a
  775. X        specific key/ptr pair out of a page.
  776. Xbtravrs.c    - function to scan forward/backwards in btree.
  777. Xbtseek.c    - internal function that navigates to leaf level. called
  778. X        in bt_insert(), bt_delete(), bt_find(), etc.
  779. Xbtzap.c        - function that resets an index.
  780. X
  781. XNotes:
  782. X1) stdio.h is not included in every module, and should not be. Unfortunately
  783. XI had to include it for NULL and BUFSIZ in a couple of places, but I hate
  784. Xhaving it wasting space when I compile stuff.
  785. X
  786. X2) btpage1.c and btpage2.c are separate because of the hairy use of macros
  787. Xand symbols that makes it hard to fit in the memory of a small compiler.
  788. Xplease keep them separate.
  789. X
  790. X3) static functions: I normally would make 99% of these functions static
  791. Xso they would not clutter up the name space, BUT, because of compiler
  792. Xspace constraints on my Amiga, and the fact that I want to be able to
  793. Xuse the page handling code in record management, I need access to them
  794. Xexternally. please do not change this. (though I may make a version of
  795. Xthis library that IS all staticed out, and all the code is in one BIG
  796. Xmodule. ick, poo.)
  797. X
  798. X4) library size: all these modules are carefully arranged so that no
  799. Xextraneous functions will get linked in (if your linker is not totally
  800. Xdead-brained). Please do not destroy that, since, IMHO, libraries should
  801. Xnever give you more than you need.
  802. X
  803. XTo Do:
  804. X1) make (if possible) the page insertion and manipulation routines
  805. Xmore portable. I simply don't know how to do this myself, so anyone
  806. Xwho knows how is invited to tell me!
  807. X
  808. X2) It would be nice if there was an EFFICIENT way to tell the tree to
  809. Xstore records off the leaves. This could be really bad, if it was not
  810. Ximplemented properly, though. If someone does this, or wants to, let
  811. Xme know.
  812. X
  813. X--mjr();
  814. END_OF_FILE
  815. if test 3983 -ne `wc -c <'b+tree/btlib/README'`; then
  816.     echo shar: \"'b+tree/btlib/README'\" unpacked with wrong size!
  817. fi
  818. # end of 'b+tree/btlib/README'
  819. fi
  820. if test -f 'b+tree/btlib/btconf.h' -a "${1}" != "-c" ; then 
  821.   echo shar: Will not clobber existing file \"'b+tree/btlib/btconf.h'\"
  822. else
  823. echo shar: Extracting \"'b+tree/btlib/btconf.h'\" \(4357 characters\)
  824. sed "s/^X//" >'b+tree/btlib/btconf.h' <<'END_OF_FILE'
  825. X#ifndef    _DEF_BT_CONFIG_H
  826. X
  827. X/*
  828. X         (C) Copyright, 1988, 1989 Marcus J. Ranum
  829. X                    All rights reserved
  830. X
  831. X
  832. X          This software, its documentation,  and  supporting
  833. X          files  are  copyrighted  material  and may only be
  834. X          distributed in accordance with the terms listed in
  835. X          the COPYRIGHT document.
  836. X*/
  837. X
  838. X
  839. X/*
  840. X    $Header: /atreus/mjr/hacks/btree/btlib/RCS/btconf.h,v 1.1 89/10/24 10:09:07 mjr Rel $
  841. X
  842. X    THIS SHOULD NOT BE INCLUDED BY USER-LEVEL PROGRAMS
  843. X
  844. X    All reasonably user-configurable options are in this file.
  845. X
  846. X    If there is something that needs to be special-cased for
  847. X    a system, put it here, PLEASE!
  848. X*/
  849. X
  850. X
  851. X/*
  852. XWARNING - there is one option that *should* be there but is in
  853. Xbtree.h because it needs to be seen by user-level programs. 
  854. XThat is the definition on bt_chrp, which is at the top of the
  855. Xfile. If you have a weird architecture, you may want to look
  856. Xat that value.
  857. X*/
  858. X
  859. X
  860. X/*
  861. XSEEK_SET should be whatever your systems version of lseek() takes
  862. Xto tell it to go to an exact offset. zero is pretty standard.
  863. X*/
  864. X#ifndef    SEEK_SET
  865. X#define    SEEK_SET    0
  866. X#endif
  867. X
  868. X/*
  869. Xif this option is turned on the bt_dump() page dump function will
  870. Xbe generated. it probably should be left out of public libraries
  871. Xbut is really handy, and it would be stupid to have to rewrite it.
  872. X
  873. X#undef    YES_BT_DEBUG
  874. X*/
  875. X#define    YES_BT_DEBUG    1
  876. X
  877. X
  878. X/*
  879. Xapparently not all compilers handle register declarations intelligently.
  880. Xthe functions in btpage1.c and btpage2.c have register declarations, 
  881. Xsometimes as many as six. if your compiler cannot handle them, just
  882. Xredefine REGISTER to be nothing.
  883. X
  884. X#define    REGISTER
  885. X*/
  886. X#define    REGISTER register
  887. X
  888. X
  889. X/*
  890. Xchoose one of these as your favorite memory copying function
  891. Xcan you believe 3 functions, 3 names, all do the same thing ?
  892. X
  893. X#define    USE_MEMCPY    1
  894. X#define    USE_MOVEMEM    1
  895. X*/
  896. X#define    USE_BCOPY    1
  897. X
  898. X/*
  899. Xif the operating system the software will be running under supports
  900. Xthe ftruncate(2) system call to free a file's allocated space after
  901. Xa certain length, turn this option on, and bt_zap() will free extra
  902. Xspace when called.
  903. X#define    USE_FTRUNCATE    0
  904. X*/
  905. X#define    USE_FTRUNCATE    1
  906. X
  907. X/*
  908. Xthe default page size. usually use BUFSIZ or maybe (BUFSIZ * 2)
  909. Xconsiderations are:: as buffer size increases, memory use for
  910. Xcache buffers increases. on the other hand, speed increases,
  911. Xdepending on the size of the tree/keys/data type. disk wastage
  912. Xalso increases, since it is possible there may be partial pages
  913. Xtaking up more space than would be taken up with smaller pages.
  914. Xsmaller pages are a win if speed is less important than disk
  915. Xwastage, though decreasing page size and boosting cache may
  916. Xoffset speed losses. this is not something that can be guessed
  917. Xat, so use BUFSIZ as a default because presumably it is good
  918. Xfor the system.
  919. X*/
  920. X#define    BT_DFLTPSIZ    BUFSIZ
  921. X
  922. X/*
  923. Xdefault magic number to use, unless a user supplies us one.
  924. Xthis can come in handy if you add it to your file(1) types
  925. Xdatabase.
  926. X*/
  927. X#define    BT_DFLTMAGIC    72251L
  928. X
  929. X/*
  930. Xdefault number of cache pages to ADD to the minimum page cache
  931. Xdo NOT simply edit this value here, since it can be set in
  932. Xcalls to bt_optopen() using BT_CACHE on a case-by-case basis.
  933. Xremember also that there are (about 4) cache buffers that will
  934. Xbe allocated no matter what, so this value is in addition to
  935. Xthe minimum cache. the minimum cache buffers are used for
  936. Xsplitting and promotion as well as page buffers, depending
  937. Xon what is being done. cache size can be overruled upwards
  938. Xby the user, so a sensible value is good here.
  939. X*/
  940. X#define    BT_DFLTCACHE    1
  941. X
  942. X/*
  943. Xdefault type of caching: read only - IE pages will always write to
  944. Xdisk when modified, but may be read out of cache directly. using
  945. Xread-only caching is the safe bet. whatever default is selected
  946. Xhere can be overruled by the user, so a safe value is OK here.
  947. X*/ 
  948. X#define    BT_DFLTCFLAG    BT_ROCACHE
  949. X
  950. X/*
  951. Xdefault data type to store: strings are a pretty good bet. this can
  952. Xbe reset anyhow in bt_optopen(), so leaving it alone is recommended.
  953. XWARNING - do not set this to be BT_USRDEF! bt_open() does not have
  954. Xany way of setting the function pointer for the comparison function.
  955. Xusing the BT_STRING data type should be encouraged anyhow, since 
  956. Xstring keys can be prefixed for greater efficiency.
  957. X*/
  958. X#define    BT_DFLTDTYPE    BT_STRING
  959. X
  960. X/*
  961. Xthat is all. this file does not need to be installed where a user
  962. Xcan include it.
  963. X*/
  964. X
  965. X#define    _DEF_BT_CONFIG_H
  966. X#endif
  967. END_OF_FILE
  968. if test 4357 -ne `wc -c <'b+tree/btlib/btconf.h'`; then
  969.     echo shar: \"'b+tree/btlib/btconf.h'\" unpacked with wrong size!
  970. fi
  971. # end of 'b+tree/btlib/btconf.h'
  972. fi
  973. if test -f 'b+tree/btlib/btdebug.c' -a "${1}" != "-c" ; then 
  974.   echo shar: Will not clobber existing file \"'b+tree/btlib/btdebug.c'\"
  975. else
  976. echo shar: Extracting \"'b+tree/btlib/btdebug.c'\" \(1897 characters\)
  977. sed "s/^X//" >'b+tree/btlib/btdebug.c' <<'END_OF_FILE'
  978. X#include    <stdio.h>
  979. X#include    <sys/types.h>
  980. X#include    "btconf.h"
  981. X#include    "btree.h"
  982. X#include    "btintern.h"
  983. X
  984. X/*
  985. X         (C) Copyright, 1988, 1989 Marcus J. Ranum
  986. X                    All rights reserved
  987. X
  988. X
  989. X          This software, its documentation,  and  supporting
  990. X          files  are  copyrighted  material  and may only be
  991. X          distributed in accordance with the terms listed in
  992. X          the COPYRIGHT document.
  993. X*/
  994. X
  995. X
  996. X#ifdef    YES_BT_DEBUG
  997. X#ifndef    lint
  998. Xstatic char *rcsid = "$Header: /atreus/mjr/hacks/btree/btlib/RCS/btdebug.c,v 1.1 89/10/24 10:08:55 mjr Rel $";
  999. X#endif
  1000. X
  1001. Xvoid
  1002. Xbt_dump(b,p)
  1003. XBT_INDEX    *b;
  1004. Xstruct    bt_cache *p;
  1005. X{
  1006. X    int    x;
  1007. X    int    rl;
  1008. X    off_t    rv;
  1009. X    char    buf[BT_DFLTPSIZ];
  1010. X
  1011. X    if(KEYUSE(p->p) > bt_pagesiz(b))
  1012. X        (void)printf("WARNING overfull page!!!\n");
  1013. X
  1014. X
  1015. X    (void)printf("Dump:page=%ld, cnt=%d, len=%d, ",
  1016. X        p->num,KEYCNT(p->p),KEYLEN(p->p));
  1017. X
  1018. X    (void)printf("lsib=%ld, rsib=%ld, high=%ld, used=%d\n",
  1019. X        LSIB(p->p),RSIB(p->p),HIPT(p->p),KEYUSE(p->p));
  1020. X
  1021. X    if(BT_MAXK(b) > sizeof(buf)) {
  1022. X        (void)printf("page size too big to dump keys (sorry)\n");
  1023. X        return;
  1024. X    }
  1025. X
  1026. X    /* print keys/len/chld index */
  1027. X    for(x = 0; x < KEYCNT(p->p); x++) {
  1028. X        if(bt_keyof(x,p->p,(bt_chrp)buf,&rl,&rv,(int)sizeof(buf)) == BT_ERR) {
  1029. X            (void)printf("cannot access key #%d\n",x);
  1030. X            return;
  1031. X        }
  1032. X
  1033. X        switch(bt_dtype(b)) {
  1034. X            case    BT_STRING:
  1035. X                buf[rl] = '\0';
  1036. X                (void)printf("key=\"%s\",len=%d,rrv=%ld",buf,rl,rv);
  1037. X                break;
  1038. X
  1039. X            case    BT_INT:
  1040. X                (void)printf("key=%d,len=%d,rrv=%ld",*(int *)buf,rl,rv);
  1041. X                break;
  1042. X
  1043. X            case    BT_LONG:
  1044. X                (void)printf("key=%ld,len=%d,rrv=%ld",*(long *)buf,rl,rv);
  1045. X                break;
  1046. X
  1047. X            case    BT_FLOAT:
  1048. X                (void)printf("key=%f,len=%d,rrv=%ld",*(float *)buf,rl,rv);
  1049. X                break;
  1050. X
  1051. X            case    BT_USRDEF:
  1052. X                (void)printf("key=<usrdef>,len=%d,rrv=%ld",rl,rv);
  1053. X                break;
  1054. X        }
  1055. X
  1056. X        if(x % 4 == 3)
  1057. X            (void)printf("\n");
  1058. X        else
  1059. X            if(x != KEYCNT(p->p) - 1)
  1060. X                (void)printf(", ");
  1061. X    }
  1062. X    (void)printf("\n");
  1063. X}
  1064. X#endif
  1065. END_OF_FILE
  1066. if test 1897 -ne `wc -c <'b+tree/btlib/btdebug.c'`; then
  1067.     echo shar: \"'b+tree/btlib/btdebug.c'\" unpacked with wrong size!
  1068. fi
  1069. # end of 'b+tree/btlib/btdebug.c'
  1070. fi
  1071. if test -f 'b+tree/btlib/btdelete.c' -a "${1}" != "-c" ; then 
  1072.   echo shar: Will not clobber existing file \"'b+tree/btlib/btdelete.c'\"
  1073. else
  1074. echo shar: Extracting \"'b+tree/btlib/btdelete.c'\" \(4335 characters\)
  1075. sed "s/^X//" >'b+tree/btlib/btdelete.c' <<'END_OF_FILE'
  1076. X#include    <sys/types.h>
  1077. X#include    <stdio.h>
  1078. X#include    "btconf.h"
  1079. X#include    "btree.h"
  1080. X#include    "btintern.h"
  1081. X
  1082. X/*
  1083. X         (C) Copyright, 1988, 1989 Marcus J. Ranum
  1084. X                    All rights reserved
  1085. X
  1086. X
  1087. X          This software, its documentation,  and  supporting
  1088. X          files  are  copyrighted  material  and may only be
  1089. X          distributed in accordance with the terms listed in
  1090. X          the COPYRIGHT document.
  1091. X*/
  1092. X
  1093. X#ifndef    lint
  1094. Xstatic char *rcsid = "$Header: /atreus/mjr/hacks/btree/btlib/RCS/btdelete.c,v 1.1 89/10/24 10:08:56 mjr Rel $";
  1095. X#endif
  1096. X
  1097. X
  1098. Xbt_delete(b,key,len)
  1099. XBT_INDEX    *b;
  1100. Xbt_chrp        key;
  1101. Xint        len;
  1102. X{
  1103. X    struct    bt_cache    *op;
  1104. X    int    staklev;
  1105. X    off_t    dpag;        /* page to delete from */
  1106. X    int    keyat;        /* key # to delete */
  1107. X    off_t    ptj;        /* junk */
  1108. X    int    sr;
  1109. X
  1110. X    /* 90% of this code is straight from bt_insert(). the only */
  1111. X    /* difference is that we need to ensure an exact match at */
  1112. X    /* leaf level only, otherwise we just track our way up the */
  1113. X    /* tree, deleting keys. page concatenation and redistribution */
  1114. X    /* are not implemented, though if they are to be, they should */
  1115. X    /* fit fairly easily in this framework. good luck, deletes suck */
  1116. X
  1117. X    /* the usual consistency checks */
  1118. X    if(len > BT_MAXK(b)) {
  1119. X        bt_errno(b) = BT_KTOOBIG;
  1120. X        return(BT_ERR);
  1121. X    }
  1122. X
  1123. X    if(len <= 0) {
  1124. X        bt_errno(b) = BT_ZEROKEY;
  1125. X        return(BT_ERR);
  1126. X    }
  1127. X
  1128. X    if(bt_seekdown(b,key,len) == BT_ERR)
  1129. X        return(BT_ERR);
  1130. X
  1131. X    /* set current stack level */
  1132. X    staklev = b->sblk.levs - 1;
  1133. X    dpag = b->stack[staklev].pg;
  1134. X
  1135. X    if((op = bt_rpage(b,dpag)) == NULL)
  1136. X        return(BT_ERR);
  1137. X
  1138. X    /* locate first del point, check if not there */
  1139. X    /* there must not be anything to delete. error. */
  1140. X    sr = bt_srchpg(key,len,bt_dtype(b),b->cmpfn,&ptj,&keyat,op->p);
  1141. X    if(sr == BT_NF)
  1142. X        return(BT_NF);
  1143. X    if(sr == BT_ERR) {
  1144. X        bt_errno(b) = BT_PAGESRCH;
  1145. X        return(BT_ERR);
  1146. X    }
  1147. X
  1148. X    /* invalidate current notion of where we are in the tree */
  1149. X    b->cpag = BT_NULL;
  1150. X
  1151. X    /* this loop should be comfortably repeated until we perform a */
  1152. X    /* simple delete without emptying a page. if a page concatentation */
  1153. X    /* function is added, we would look until we no longer concatenate */
  1154. X    while(1) {
  1155. X
  1156. X        /* oddball special case. if the page is root and */
  1157. X        /* there is no key left to delete, the tree is */
  1158. X        /* (by definition) empty, having only a high pointer */
  1159. X        /* left. so, the high pointer is dropped, and */
  1160. X        /* turned to BT_NULL, instantly converting root */
  1161. X        /* back to a leaf page. we then return. done */
  1162. X        if(dpag == b->sblk.root && KEYCNT(op->p) == 0) {
  1163. X            HIPT(op->p) = BT_NULL;
  1164. X            KEYLEN(op->p) = 0;
  1165. X            op->flags = BT_CHE_DIRTY;
  1166. X            if(bt_wpage(b,op) == BT_ERR)
  1167. X                return(BT_ERR);
  1168. X            b->sblk.levs = 1;
  1169. X            if(bt_wsuper(b) == BT_ERR)
  1170. X                return(BT_ERR);
  1171. X            return(BT_OK);
  1172. X        }
  1173. X
  1174. X        /* if the page has more than one key OR is an index with */
  1175. X        /* one key, just drop one key from the page, do not free it */
  1176. X        /* also, if the page is the root page, do not do free it */
  1177. X        if(KEYCNT(op->p) > 1 || dpag == b->sblk.root ||
  1178. X            (KEYCNT(op->p) == 1 && HIPT(op->p) != BT_NULL)) {
  1179. X            struct    bt_cache *tp;    /* temp copy page */
  1180. X
  1181. X            if((tp = bt_rpage(b,BT_NULL)) == NULL)
  1182. X                return(BT_ERR);
  1183. X            bt_delpg(keyat,op->p,tp->p);
  1184. X
  1185. X            /* swap the page numbers, invalidate the old, */
  1186. X            /* mark the new as dirty to force a write */
  1187. X            tp->num = op->num;
  1188. X            tp->flags = BT_CHE_DIRTY;
  1189. X            op->num = BT_NULL;
  1190. X
  1191. X            if(bt_wpage(b,op) == BT_ERR || bt_wpage(b,tp) == BT_ERR)
  1192. X                return(BT_ERR);
  1193. X
  1194. X            /* mark all as well with tree */
  1195. X            bt_clearerr(b);
  1196. X            return(BT_OK);
  1197. X        } else {
  1198. X            off_t    savlft;
  1199. X            off_t    savrt;
  1200. X
  1201. X            savlft = LSIB(op->p);
  1202. X            savrt = RSIB(op->p);
  1203. X
  1204. X            if(savlft != BT_NULL) {
  1205. X                if((op = bt_rpage(b,savlft)) == NULL)
  1206. X                    return(BT_ERR);
  1207. X                RSIB(op->p) = savrt;
  1208. X                op->flags = BT_CHE_DIRTY;
  1209. X                if(bt_wpage(b,op) == BT_ERR)
  1210. X                    return(BT_ERR);
  1211. X            }
  1212. X
  1213. X            if(savrt != BT_NULL) {
  1214. X                if((op = bt_rpage(b,savrt)) == NULL)
  1215. X                    return(BT_ERR);
  1216. X                LSIB(op->p) = savlft;
  1217. X                op->flags = BT_CHE_DIRTY;
  1218. X                if(bt_wpage(b,op) == BT_ERR)
  1219. X                    return(BT_ERR);
  1220. X            }
  1221. X
  1222. X            /* sibs are fixed, now free the page */
  1223. X            if(bt_freepage(b,dpag) == BT_ERR)
  1224. X                return(BT_ERR);
  1225. X        }
  1226. X
  1227. X        /* still going, pop stack level */
  1228. X        staklev--;
  1229. X
  1230. X        /* set key location for next delete */
  1231. X        keyat = b->stack[staklev].ky;
  1232. X        dpag = b->stack[staklev].pg;
  1233. X
  1234. X        /* allocate a scratch page and read the old */
  1235. X        if((op = bt_rpage(b,dpag)) == NULL)
  1236. X            return(BT_ERR);
  1237. X
  1238. X    }
  1239. X}
  1240. END_OF_FILE
  1241. if test 4335 -ne `wc -c <'b+tree/btlib/btdelete.c'`; then
  1242.     echo shar: \"'b+tree/btlib/btdelete.c'\" unpacked with wrong size!
  1243. fi
  1244. # end of 'b+tree/btlib/btdelete.c'
  1245. fi
  1246. if test -f 'b+tree/btlib/btload.c' -a "${1}" != "-c" ; then 
  1247.   echo shar: Will not clobber existing file \"'b+tree/btlib/btload.c'\"
  1248. else
  1249. echo shar: Extracting \"'b+tree/btlib/btload.c'\" \(4231 characters\)
  1250. sed "s/^X//" >'b+tree/btlib/btload.c' <<'END_OF_FILE'
  1251. X#include    <sys/types.h>
  1252. X#include    <stdio.h>
  1253. X#include    "btconf.h"
  1254. X#include    "btree.h"
  1255. X#include    "btintern.h"
  1256. X
  1257. X/*
  1258. X         (C) Copyright, 1988, 1989 Marcus J. Ranum
  1259. X                    All rights reserved
  1260. X
  1261. X
  1262. X          This software, its documentation,  and  supporting
  1263. X          files  are  copyrighted  material  and may only be
  1264. X          distributed in accordance with the terms listed in
  1265. X          the COPYRIGHT document.
  1266. X*/
  1267. X
  1268. X
  1269. X#ifndef    lint
  1270. Xstatic char *rcsid = "$Header: /atreus/mjr/hacks/btree/btlib/RCS/btload.c,v 1.1 89/10/24 10:08:59 mjr Rel $";
  1271. X#endif
  1272. X
  1273. Xextern    char    *realloc();
  1274. X
  1275. Xbt_load(b,key,len,rrn,flag)
  1276. XBT_INDEX    *b;
  1277. Xbt_chrp        key;
  1278. Xint        len;
  1279. Xoff_t        rrn;
  1280. Xint        flag;
  1281. X{
  1282. X    struct    bt_cache *op = NULL;
  1283. X    struct    bt_cache *np = NULL;
  1284. X    off_t    irrn;
  1285. X    off_t    savold = BT_NULL;
  1286. X    int    slev;
  1287. X
  1288. X    /* first insert is always at leaf lev. */
  1289. X    /* note that we use the stack backwards here */
  1290. X    slev = 0;
  1291. X
  1292. X    irrn = rrn;
  1293. X
  1294. X    /* if flag is BOF, zap the tree and ready for load */
  1295. X    if(flag == BT_BOF) {
  1296. X        return(bt_zap(b));
  1297. X    } 
  1298. X
  1299. X    /* if flag is BT_EOF close up and finish the tree */
  1300. X    if(flag == BT_EOF) {
  1301. X        return(BT_OK);
  1302. X    }
  1303. X
  1304. X    /* if the flag is wrong, die. */
  1305. X    if(flag != BT_OK) {
  1306. X        bt_errno(b) = BT_BADUSERARG;
  1307. X        return(BT_ERR);
  1308. X    }
  1309. X
  1310. X    /* safety valves */
  1311. X    if(len > BT_MAXK(b)) {
  1312. X        bt_errno(b) = BT_KTOOBIG;
  1313. X        return(BT_ERR);
  1314. X    }
  1315. X
  1316. X    if(len <= 0) {
  1317. X        bt_errno(b) = BT_ZEROKEY;
  1318. X        return(BT_ERR);
  1319. X    }
  1320. X
  1321. X    /* set the bottom of the stack */
  1322. X    b->stack[b->sblk.levs - 1].pg = b->sblk.root;
  1323. X
  1324. X
  1325. X    /* this is similar to insert, but simpler */
  1326. X    while(1) {
  1327. X
  1328. X        if((op = bt_rpage(b,b->stack[slev].pg)) == NULL)
  1329. X            goto bombout;
  1330. X
  1331. X        /* if key will fit in page, perform simple insert */
  1332. X        if((int)KEYUSE(op->p) + len + sizeof(int) + sizeof(off_t) < bt_pagesiz(b)) {
  1333. X            if((np = bt_rpage(b,BT_NULL)) == NULL)
  1334. X                goto bombout;
  1335. X
  1336. X            bt_inspg(key,len,&irrn,0,op->p,np->p);
  1337. X
  1338. X            /* adjust caching and write */
  1339. X            np->num = op->num;
  1340. X            np->flags = BT_CHE_DIRTY;
  1341. X            op->num = BT_NULL;
  1342. X
  1343. X            if(bt_wpage(b,op) == BT_ERR || bt_wpage(b,np) == BT_ERR)
  1344. X                    return(BT_ERR);
  1345. X
  1346. X            /* e finito */
  1347. X            bt_clearerr(b);
  1348. X            return(BT_OK);
  1349. X        } else {
  1350. X            off_t    npag;
  1351. X            int    indexsplit = 0;
  1352. X
  1353. X            if((npag = bt_newpage(b)) == BT_NULL)
  1354. X                goto bombout;
  1355. X
  1356. X            if(HIPT(op->p) != BT_NULL)
  1357. X                indexsplit++;
  1358. X
  1359. X            /* fix up left sib in old page and start new */
  1360. X            LSIB(op->p) = npag;        
  1361. X            op->flags = BT_CHE_DIRTY;
  1362. X
  1363. X            if(bt_wpage(b,op) == BT_ERR)
  1364. X                goto bombout;
  1365. X
  1366. X            if((np = bt_rpage(b,BT_NULL)) == NULL)
  1367. X                goto bombout;
  1368. X
  1369. X            KEYCNT(np->p) = KEYLEN(np->p) = 0;
  1370. X            RSIB(np->p) = b->stack[slev].pg;
  1371. X            LSIB(np->p) = HIPT(np->p) = BT_NULL;
  1372. X
  1373. X            if(!indexsplit) {
  1374. X                if((op = bt_rpage(b,BT_NULL)) == NULL)
  1375. X                    goto bombout;
  1376. X
  1377. X                bt_inspg(key,len,&irrn,0,np->p,op->p);
  1378. X                np->num = BT_NULL;
  1379. X                op->num = npag;
  1380. X                op->flags = BT_CHE_DIRTY;
  1381. X                if(bt_wpage(b,np) == BT_ERR ||
  1382. X                    bt_wpage(b,op) == BT_ERR)
  1383. X                        goto bombout;
  1384. X            } else {
  1385. X                HIPT(np->p) = irrn;
  1386. X                np->num = npag;
  1387. X                np->flags = BT_CHE_DIRTY;
  1388. X                if(bt_wpage(b,np) == BT_ERR)
  1389. X                    goto bombout;
  1390. X            }
  1391. X
  1392. X            /* new rrn is new page */
  1393. X            irrn = npag;
  1394. X
  1395. X            /* new current page is the new page */
  1396. X            /* at this point the old one is history */
  1397. X            savold = b->stack[slev].pg;
  1398. X            b->stack[slev].pg = npag;
  1399. X        }
  1400. X
  1401. X        /* pop down a level (really up) */
  1402. X        slev++;
  1403. X        /* dynamically deal w/ stack overruns */
  1404. X        if(b->sblk.levs == b->shih - 2) {
  1405. X            b->shih += 3;
  1406. X            b->stack = (struct bt_stack *)realloc((char *)b->stack,(unsigned)(b->shih * sizeof(struct bt_stack)));
  1407. X            if(b->stack == NULL)
  1408. X                return(BT_ERR);
  1409. X        }
  1410. X
  1411. X        /* do we need a new root page ? */
  1412. X        if(slev == b->sblk.levs) {
  1413. X            if((b->sblk.root = bt_newpage(b)) == BT_NULL)
  1414. X                goto bombout;
  1415. X
  1416. X            if((op = bt_rpage(b,BT_NULL)) == NULL)
  1417. X                goto bombout;
  1418. X
  1419. X            /* set it up as blank except the high pointer */
  1420. X            /* on the next iteration, the key will be inserted */
  1421. X            LSIB(op->p) = RSIB(op->p) = BT_NULL;
  1422. X            KEYLEN(op->p) = KEYCNT(op->p) = 0;
  1423. X            HIPT(op->p) = savold;
  1424. X
  1425. X            op->num = b->sblk.root;
  1426. X            op->flags = BT_CHE_DIRTY;
  1427. X
  1428. X            b->dirt++;
  1429. X            b->sblk.levs++;
  1430. X
  1431. X            b->stack[b->sblk.levs - 1].pg = b->sblk.root;
  1432. X            if(bt_wpage(b,op) == BT_ERR || bt_wsuper(b) == BT_ERR)
  1433. X                goto bombout;
  1434. X        }
  1435. X    }
  1436. X
  1437. X    /* argh ! */
  1438. Xbombout:
  1439. X    if(op != NULL)
  1440. X        (void)bt_wpage(b,op);
  1441. X    if(np != NULL)
  1442. X        (void)bt_wpage(b,np);
  1443. X    return(BT_ERR);
  1444. X}
  1445. END_OF_FILE
  1446. if test 4231 -ne `wc -c <'b+tree/btlib/btload.c'`; then
  1447.     echo shar: \"'b+tree/btlib/btload.c'\" unpacked with wrong size!
  1448. fi
  1449. # end of 'b+tree/btlib/btload.c'
  1450. fi
  1451. if test -f 'b+tree/btlib/btopen.c' -a "${1}" != "-c" ; then 
  1452.   echo shar: Will not clobber existing file \"'b+tree/btlib/btopen.c'\"
  1453. else
  1454. echo shar: Extracting \"'b+tree/btlib/btopen.c'\" \(3058 characters\)
  1455. sed "s/^X//" >'b+tree/btlib/btopen.c' <<'END_OF_FILE'
  1456. X#include    <sys/types.h>
  1457. X#include    <sys/file.h>
  1458. X#include    <stdio.h>
  1459. X#include    "btconf.h"
  1460. X#include    "btree.h"
  1461. X#include    "btintern.h"
  1462. X
  1463. X/*
  1464. X         (C) Copyright, 1988, 1989 Marcus J. Ranum
  1465. X                    All rights reserved
  1466. X
  1467. X
  1468. X          This software, its documentation,  and  supporting
  1469. X          files  are  copyrighted  material  and may only be
  1470. X          distributed in accordance with the terms listed in
  1471. X          the COPYRIGHT document.
  1472. X*/
  1473. X
  1474. X
  1475. X#ifndef    lint
  1476. Xstatic char *rcsid = "$Header: /atreus/mjr/hacks/btree/btlib/RCS/btopen.c,v 1.1 89/10/24 10:09:00 mjr Rel $";
  1477. X#endif
  1478. X
  1479. Xextern    char    *malloc();
  1480. Xextern    off_t    lseek();
  1481. X
  1482. X
  1483. XBT_INDEX    *
  1484. Xbt_open(path,flags,mode)
  1485. Xchar    *path;
  1486. Xint    flags;
  1487. Xint    mode;
  1488. X{
  1489. X    BT_INDEX    *ret;
  1490. X    struct bt_cache *cp1;
  1491. X    struct bt_cache *cp2;
  1492. X    int        r;
  1493. X
  1494. X    if((ret = (BT_INDEX *)malloc(sizeof(BT_INDEX))) == NULL)
  1495. X        return(NULL);
  1496. X
  1497. X    /* clear error */
  1498. X    bt_errno(ret) = BT_NOERROR;
  1499. X
  1500. X    /* set funcp to something inoffensive */
  1501. X    bt_cmpfn(ret) = 0;
  1502. X
  1503. X    if((bt_fileno(ret) = open(path,(flags|O_RDWR),mode)) < 0)
  1504. X        goto bombout;
  1505. X
  1506. X    r = read(bt_fileno(ret),(char *)&ret->sblk,sizeof(struct bt_super));
  1507. X
  1508. X    /* failure to read anything - initialize tree */
  1509. X    if(r == 0) {
  1510. X        char    *jnk;
  1511. X        if((jnk = malloc((unsigned)BT_DFLTPSIZ)) != NULL) {
  1512. X            ret->sblk.magic = BT_DFLTMAGIC;
  1513. X            bt_pagesiz(ret) = BT_DFLTPSIZ;
  1514. X            bt_dtype(ret) = BT_DFLTDTYPE;
  1515. X            ret->sblk.levs = 1;
  1516. X            ret->sblk.root = (off_t)BT_DFLTPSIZ;
  1517. X            ret->sblk.free = BT_NULL;
  1518. X            ret->sblk.high = (off_t)(2 * BT_DFLTPSIZ);
  1519. X
  1520. X            /* mark super block as dirty and sync */
  1521. X            ret->dirt = 1;
  1522. X
  1523. X            /* write and pretend we read a legit superblock */
  1524. X            if(bt_wsuper(ret) == BT_OK)
  1525. X                r = sizeof(struct bt_super);
  1526. X
  1527. X            /* now make jnk into an empty first page */
  1528. X            KEYCNT(jnk) = 0;
  1529. X            KEYLEN(jnk) = 0;
  1530. X            LSIB(jnk) = RSIB(jnk) = BT_NULL;
  1531. X            HIPT(jnk) = BT_NULL;
  1532. X
  1533. X            /* now, since the cache is not set up yet, we */
  1534. X            /* must directly write the page. */
  1535. X            if(lseek(bt_fileno(ret),(off_t)BT_DFLTPSIZ,SEEK_SET) != (off_t)BT_DFLTPSIZ ||
  1536. X                write(bt_fileno(ret),jnk,BT_DFLTPSIZ) != BT_DFLTPSIZ)
  1537. X                r = 0;
  1538. X            (void)free(jnk);
  1539. X        }
  1540. X    }
  1541. X
  1542. X    /* yet another sanity check */
  1543. X    if(r != sizeof(struct bt_super) || ret->sblk.magic != BT_DFLTMAGIC)
  1544. X        goto bombout;
  1545. X
  1546. X    /* initialize locator stack */
  1547. X    ret->shih = ret->sblk.levs + 2;
  1548. X    ret->stack = (struct bt_stack *)malloc((unsigned)(ret->shih * sizeof(struct bt_stack)));
  1549. X    if(ret->stack == NULL)
  1550. X        goto bombout;
  1551. X
  1552. X    /* initialize cache */
  1553. X    cp2 = ret->lru = NULL;
  1554. X    for(r = 0; r < BT_MINCACHE + BT_DFLTCACHE; r++) {
  1555. X        cp1 = (struct bt_cache *)malloc(sizeof(struct bt_cache)); 
  1556. X        if(cp1 == NULL)
  1557. X            goto bombout;
  1558. X
  1559. X        if(ret->lru == NULL)
  1560. X            ret->lru = cp1;
  1561. X        cp1->prev = cp2;
  1562. X        cp1->num = BT_NULL;
  1563. X        cp1->next = NULL;
  1564. X        cp1->flags = BT_CHE_CLEAN;
  1565. X        if((cp1->p = (bt_chrp)malloc((unsigned)bt_pagesiz(ret))) == NULL)
  1566. X            goto bombout;
  1567. X        if(cp2 != NULL)
  1568. X            cp2->next = cp1;
  1569. X
  1570. X        cp2 = cp1;
  1571. X    }
  1572. X    ret->mru = cp1;
  1573. X
  1574. X    /* set cache type flag */
  1575. X    ret->cflg = BT_DFLTCFLAG;
  1576. X
  1577. X    /* no valid current key */
  1578. X    ret->cpag = BT_NULL;
  1579. X
  1580. X    /* all is well */
  1581. X    return(ret);
  1582. X
  1583. Xbombout:
  1584. X    (void)bt_close(ret);
  1585. X    return(NULL);
  1586. X}
  1587. END_OF_FILE
  1588. if test 3058 -ne `wc -c <'b+tree/btlib/btopen.c'`; then
  1589.     echo shar: \"'b+tree/btlib/btopen.c'\" unpacked with wrong size!
  1590. fi
  1591. # end of 'b+tree/btlib/btopen.c'
  1592. fi
  1593. if test -f 'b+tree/btlib/btravrs.c' -a "${1}" != "-c" ; then 
  1594.   echo shar: Will not clobber existing file \"'b+tree/btlib/btravrs.c'\"
  1595. else
  1596. echo shar: Extracting \"'b+tree/btlib/btravrs.c'\" \(1977 characters\)
  1597. sed "s/^X//" >'b+tree/btlib/btravrs.c' <<'END_OF_FILE'
  1598. X#include    <sys/types.h>
  1599. X#include    <stdio.h>
  1600. X#include    "btconf.h"
  1601. X#include    "btree.h"
  1602. X#include    "btintern.h"
  1603. X
  1604. X/*
  1605. X         (C) Copyright, 1988, 1989 Marcus J. Ranum
  1606. X                    All rights reserved
  1607. X
  1608. X
  1609. X          This software, its documentation,  and  supporting
  1610. X          files  are  copyrighted  material  and may only be
  1611. X          distributed in accordance with the terms listed in
  1612. X          the COPYRIGHT document.
  1613. X*/
  1614. X
  1615. X
  1616. X#ifndef    lint
  1617. Xstatic char *rcsid = "$Header: /atreus/mjr/hacks/btree/btlib/RCS/btravrs.c,v 1.1 89/10/24 10:09:06 mjr Rel $";
  1618. X#endif
  1619. X
  1620. Xbt_traverse(b,d,kbuf,maxlen,retlen,retrrv)
  1621. XBT_INDEX    *b;
  1622. Xint        d;
  1623. Xbt_chrp        kbuf;
  1624. Xint        maxlen;
  1625. Xint        *retlen;
  1626. Xoff_t        *retrrv;
  1627. X{
  1628. X    struct    bt_cache *p;
  1629. X    off_t    savp;
  1630. X
  1631. X    /* if the current page is not set, just zing up to the head */
  1632. X    /* or the tail - the opposite side of the tree, whatever it is */
  1633. X    if(b->cpag == BT_NULL)
  1634. X        if(bt_goto(b,d == BT_EOF ? BT_BOF:BT_EOF) == BT_ERR) 
  1635. X            return(BT_ERR);
  1636. X
  1637. X    /* save */
  1638. X    savp = b->cpag;
  1639. X
  1640. X    if((p = bt_rpage(b,b->cpag)) == NULL)
  1641. X        return(BT_ERR);
  1642. X
  1643. X    /* adjust current key # */
  1644. X    if(d == BT_EOF)
  1645. X        b->cky++;
  1646. X    else
  1647. X        b->cky--;
  1648. X
  1649. X    /* have we run out of keys in the page ? */
  1650. X    while((d == BT_EOF && b->cky >=  KEYCNT(p->p)) || 
  1651. X        (d == BT_BOF && b->cky < 0)) {
  1652. X
  1653. X        if(d == BT_EOF)
  1654. X            b->cpag = RSIB(p->p);
  1655. X        else
  1656. X            b->cpag = LSIB(p->p);
  1657. X
  1658. X        /* we are there - wherever there is */
  1659. X        if(b->cpag != BT_NULL) {
  1660. X            if((p = bt_rpage(b,b->cpag)) == NULL)
  1661. X                return(BT_ERR);
  1662. X
  1663. X            /* reset current key */
  1664. X            if(d == BT_EOF)
  1665. X                b->cky = 0;
  1666. X            else
  1667. X                b->cky = KEYCNT(p->p) - 1;
  1668. X        } else {
  1669. X            /* we have actually HIT the end */
  1670. X            /* restore current page */
  1671. X            b->cpag = savp;
  1672. X            /* and point the key just past the end of the page */
  1673. X            if(d == BT_EOF)
  1674. X                b->cky = KEYCNT(p->p);
  1675. X            else
  1676. X                b->cky = -1;
  1677. X            *retlen = 0;
  1678. X            *retrrv = 0;
  1679. X            return(d);
  1680. X        }
  1681. X    }
  1682. X
  1683. X    if(bt_keyof(b->cky,p->p,kbuf,retlen,retrrv,maxlen) == BT_ERR)
  1684. X        return(BT_ERR);
  1685. X
  1686. X    /* mark all as well with tree */
  1687. X    bt_clearerr(b);
  1688. X    return(BT_OK);
  1689. X}
  1690. END_OF_FILE
  1691. if test 1977 -ne `wc -c <'b+tree/btlib/btravrs.c'`; then
  1692.     echo shar: \"'b+tree/btlib/btravrs.c'\" unpacked with wrong size!
  1693. fi
  1694. # end of 'b+tree/btlib/btravrs.c'
  1695. fi
  1696. if test -f 'b+tree/btlib/btree.h' -a "${1}" != "-c" ; then 
  1697.   echo shar: Will not clobber existing file \"'b+tree/btlib/btree.h'\"
  1698. else
  1699. echo shar: Extracting \"'b+tree/btlib/btree.h'\" \(2984 characters\)
  1700. sed "s/^X//" >'b+tree/btlib/btree.h' <<'END_OF_FILE'
  1701. X#ifndef    _DEF_BTREE_H
  1702. X
  1703. X/*
  1704. X         (C) Copyright, 1988, 1989 Marcus J. Ranum
  1705. X                    All rights reserved
  1706. X
  1707. X
  1708. X          This software, its documentation,  and  supporting
  1709. X          files  are  copyrighted  material  and may only be
  1710. X          distributed in accordance with the terms listed in
  1711. X          the COPYRIGHT document.
  1712. X*/
  1713. X
  1714. X
  1715. X/*
  1716. X    $Header: /atreus/mjr/hacks/btree/btlib/RCS/btree.h,v 1.1 89/10/24 10:09:07 mjr Rel $
  1717. X*/
  1718. X
  1719. X
  1720. X/*
  1721. Xthere are some potential problems with just using char * instead of
  1722. Xunsigned char *, because of sign extension and so on. the following
  1723. Xtypedef indicates the best type to use as a pointer to an arbitrary
  1724. Xchunk of data for the system. since a lot of pointer math is done on
  1725. Xthese, it should be either a signed or unsigned char, or odd results
  1726. Xmay occur.
  1727. Xtypedef    char *        bt_chrp;
  1728. X*/
  1729. Xtypedef    unsigned char *    bt_chrp;
  1730. X
  1731. X
  1732. X/* return codes */
  1733. X#define    BT_OK    0
  1734. X#define    BT_ERR    -1
  1735. X#define    BT_NF    1
  1736. X#define    BT_EOF    2
  1737. X#define    BT_BOF    3
  1738. X
  1739. X/* arguments to bt_optopen */
  1740. X#define    BT_PATH        1
  1741. X#define    BT_PSIZE    2
  1742. X#define    BT_CACHE    3
  1743. X#define    BT_CFLAG    4
  1744. X#define    BT_OMODE    5
  1745. X#define    BT_OPERM    6
  1746. X#define    BT_MAGIC    7
  1747. X#define    BT_DTYPE    8
  1748. X#define    BT_LABEL    9
  1749. X
  1750. X/* cache modes, acceptable argument to BT_CFLAG */
  1751. X#define    BT_NOCACHE    0
  1752. X#define    BT_ROCACHE    1
  1753. X#define    BT_RWCACHE    2
  1754. X
  1755. X/* recognized data types, acceptable argument to BT_DTYPE */
  1756. X#define    BT_STRING    0
  1757. X#define    BT_INT        1
  1758. X#define    BT_LONG        2
  1759. X#define    BT_FLOAT    3
  1760. X#define    BT_USRDEF    4
  1761. X
  1762. X/* cache handle */
  1763. Xstruct    bt_cache {
  1764. X    char    flags;
  1765. X    bt_chrp    p;
  1766. X    off_t    num;
  1767. X    struct    bt_cache *next;
  1768. X    struct    bt_cache *prev;
  1769. X};
  1770. X
  1771. X/* super block */
  1772. Xstruct    bt_super {
  1773. X    long    magic;
  1774. X    int    psiz;
  1775. X    int    levs;
  1776. X    int    dtyp;
  1777. X    off_t    root;
  1778. X    off_t    free;
  1779. X    off_t    high;
  1780. X};
  1781. X
  1782. Xstruct    bt_stack {
  1783. X    off_t    pg;
  1784. X    int    ky;
  1785. X};
  1786. X
  1787. X/* b+tree index handle */
  1788. Xstruct    bt_index {
  1789. X    int    fd;
  1790. X    int    errno;
  1791. X    char    dirt;
  1792. X    int    cflg;
  1793. X    int    cky;
  1794. X    off_t    cpag;
  1795. X    int    (*cmpfn)();
  1796. X    struct    bt_super sblk;
  1797. X    struct    bt_cache *lru;
  1798. X    struct    bt_cache *mru;
  1799. X    struct    bt_stack *stack;
  1800. X    int    shih;
  1801. X};
  1802. X#define    BT_INDEX    struct bt_index
  1803. X
  1804. X/* pseudo functions */
  1805. X#define    bt_fileno(b)    (b->fd)
  1806. X#define    bt_pagesiz(b)    (b->sblk.psiz)
  1807. X#define    bt_dtype(b)    (b->sblk.dtyp)
  1808. X#define    bt_cmpfn(b)    (b->cmpfn)
  1809. X#define    bt_errno(b)    (b->errno)
  1810. X#define    bt_clearerr(b)    (b->errno = BT_NOERROR)
  1811. X
  1812. X/* biggest size of a key - depends on the page size of the tree */
  1813. X#define    BT_MAXK(b)    (((b->sblk.psiz-(4*sizeof(int))-(5*sizeof(off_t)))/2) - sizeof(off_t))
  1814. X
  1815. X/* size of page 0 label - depends on the page size and sblk size */
  1816. X#define    BT_LABSIZ(b)    (b->sblk.psiz - (sizeof(struct bt_super) + 1))
  1817. X
  1818. X/* forward decls. */
  1819. Xextern    BT_INDEX    *bt_open();
  1820. Xextern    BT_INDEX    *bt_optopen();
  1821. Xextern    void        bt_perror();
  1822. X
  1823. X/* btree error codes and messages */
  1824. Xextern    char    *bt_errs[];
  1825. X
  1826. X/* error constants */
  1827. X#define    BT_NOERROR    0
  1828. X#define    BT_KTOOBIG    1
  1829. X#define    BT_ZEROKEY    2
  1830. X#define    BT_DUPKEY    3
  1831. X#define    BT_PTRINVAL    4
  1832. X#define    BT_NOBUFFERS    5
  1833. X#define    BT_LTOOBIG    6
  1834. X#define    BT_BTOOSMALL    7
  1835. X#define    BT_BADPAGE    8
  1836. X#define    BT_PAGESRCH    9
  1837. X#define    BT_BADUSERARG    10
  1838. X
  1839. X#define    _DEF_BTREE_H
  1840. X#endif
  1841. END_OF_FILE
  1842. if test 2984 -ne `wc -c <'b+tree/btlib/btree.h'`; then
  1843.     echo shar: \"'b+tree/btlib/btree.h'\" unpacked with wrong size!
  1844. fi
  1845. # end of 'b+tree/btlib/btree.h'
  1846. fi
  1847. if test -f 'b+tree/utils/Makefile' -a "${1}" != "-c" ; then 
  1848.   echo shar: Will not clobber existing file \"'b+tree/utils/Makefile'\"
  1849. else
  1850. echo shar: Extracting \"'b+tree/utils/Makefile'\" \(1773 characters\)
  1851. sed "s/^X//" >'b+tree/utils/Makefile' <<'END_OF_FILE'
  1852. X# 
  1853. X#
  1854. X#/*
  1855. X#         (C) Copyright, 1988, 1989 Marcus J. Ranum
  1856. X#                    All rights reserved
  1857. X#
  1858. X#
  1859. X#          This software, its documentation,  and  supporting
  1860. X#          files  are  copyrighted  material  and may only be
  1861. X#          distributed in accordance with the terms listed in
  1862. X#          the COPYRIGHT document.
  1863. X#*/
  1864. X#
  1865. X# $Header: /atreus/mjr/hacks/btree/utils/RCS/Makefile,v 1.1 89/10/24 10:09:30 mjr Rel $
  1866. X#
  1867. X
  1868. XBTHDRDIR=../btlib
  1869. XDBHDRDIR=../btdbmlib
  1870. X
  1871. XLIBDIR=..
  1872. XBTLIB= $(LIBDIR)/libbtree.a
  1873. XDBLIB= $(LIBDIR)/libbtdbm.a
  1874. X
  1875. X# if compiled with -DBTOPEN test programs will use simpler version
  1876. X# of open that is smaller and has less frills
  1877. X# if compiled with -DDEBUG, testrack will give an idea of what is
  1878. X# going on inside
  1879. X
  1880. XCC= cc
  1881. X
  1882. X#CFLAGS = -I$(BTHDRDIR) -I$(DBHDRDIR) -g
  1883. X#CFLAGS = -I$(BTHDRDIR) -I$(DBHDRDIR) -p -DDEBUG
  1884. XCFLAGS = -I$(BTHDRDIR) -I$(DBHDRDIR) -O
  1885. X
  1886. XLDFLAGS = -p
  1887. X#LDFLAGS = -s
  1888. X
  1889. X
  1890. XCFILES=        testrack.c \
  1891. X        words.c \
  1892. X        btoptim.c \
  1893. X        rectest.c \
  1894. X        dbtest.c \
  1895. X        btest.c
  1896. X
  1897. Xall:    testrack btest rectest dbtest words btoptim
  1898. X
  1899. Xtestrack:    testrack.o $(BTLIB)
  1900. X    $(CC) $(LDFLAGS) -o testrack testrack.o $(BTLIB)
  1901. X
  1902. Xbtest:    btest.o $(BTLIB)
  1903. X    $(CC) $(LDFLAGS) -o btest btest.o $(BTLIB)
  1904. X
  1905. Xrectest:    rectest.o $(DBLIB)
  1906. X    $(CC) $(LDFLAGS) -o rectest rectest.o $(DBLIB)
  1907. X
  1908. Xdbtest:    dbtest.o $(DBLIB) $(BTLIB)
  1909. X    $(CC) $(LDFLAGS) -o dbtest dbtest.o $(DBLIB) $(BTLIB)
  1910. X
  1911. Xwords:    words.o
  1912. X    $(CC) $(LDFLAGS) -o words words.o
  1913. X
  1914. Xbtoptim:    btoptim.o $(BTLIB)
  1915. X    $(CC) $(LDFLAGS) -o btoptim btoptim.o $(BTLIB)
  1916. X
  1917. Xflog:    testrack words flog.sh
  1918. X    sh flog.sh
  1919. X
  1920. Xclean:
  1921. X    rm -f testrack words btest *.o core input input.srt test.dat \
  1922. X    test2.dat btoptim rectest dbtest
  1923. X
  1924. Xlint:
  1925. X    lint -I$(BTHDRDIR) -I$(DBHDRDIR) -u $(CFILES) | sed '/pointer alignment/d'
  1926. X
  1927. Xci:    clean
  1928. X    ci -u $(CFILES) flog.sh Makefile README < /dev/null
  1929. END_OF_FILE
  1930. if test 1773 -ne `wc -c <'b+tree/utils/Makefile'`; then
  1931.     echo shar: \"'b+tree/utils/Makefile'\" unpacked with wrong size!
  1932. fi
  1933. # end of 'b+tree/utils/Makefile'
  1934. fi
  1935. if test -f 'b+tree/utils/README' -a "${1}" != "-c" ; then 
  1936.   echo shar: Will not clobber existing file \"'b+tree/utils/README'\"
  1937. else
  1938. echo shar: Extracting \"'b+tree/utils/README'\" \(1953 characters\)
  1939. sed "s/^X//" >'b+tree/utils/README' <<'END_OF_FILE'
  1940. X
  1941. X
  1942. X/*
  1943. X         (C) Copyright, 1988, 1989 Marcus J. Ranum
  1944. X                    All rights reserved
  1945. X
  1946. X
  1947. X          This software, its documentation,  and  supporting
  1948. X          files  are  copyrighted  material  and may only be
  1949. X          distributed in accordance with the terms listed in
  1950. X          the COPYRIGHT document.
  1951. X*/
  1952. X
  1953. X    The test program "btflog.sh" is a good way of seeing if
  1954. Xthe btree routines work on your system. for the first test runs
  1955. Xyou may wish to edit some of the parameters at the top of btflog.sh
  1956. X- or just type "make flog" and watch.
  1957. X
  1958. X
  1959. X
  1960. XContents::
  1961. XMakefile    - self explanatory.
  1962. X
  1963. XREADME        - this.
  1964. X
  1965. Xbtest.c        - test harness and btree debugger (of sorts). this
  1966. X        program breaks a lot of rules, by making use of 
  1967. X        some of the internal b+tree functions. at least
  1968. X        if you're going to do it, you'll have some examples.
  1969. X        Do NOT use btest as a means of judging the speed
  1970. X        of the library, since the input-interpreting
  1971. X        routines in it are pretty slow.
  1972. X
  1973. Xdbtest.c    - test harness for the dbm-clone library built on
  1974. X        the store library.
  1975. X
  1976. Xrectest.c    - test harness for the store library.
  1977. X
  1978. Xflog.sh        - a bourne shell script that pounds an index or two on
  1979. X        its head by having randwords make a list of garbage, and
  1980. X        then inserting it, deleting it, and so on.
  1981. X
  1982. Xwords.c        - junk word maker for btree test rack.
  1983. X
  1984. Xbtoptim.c    - a simple program that copies one index out, in
  1985. X        reverse sort order, and does an optimal load
  1986. X        of the index into a new one.
  1987. X
  1988. Xtestrack.c    - test driver containing several different tests,
  1989. X        each of which tries to match the expected state of
  1990. X        the tree against the real state, and so on. the
  1991. X        key values to change when flogging the code are the
  1992. X        number and length of random words to insert, and
  1993. X        the page size of the test trees.
  1994. X
  1995. XNotes:
  1996. X        the code in btest.c uses a few icky hackerish tricks,
  1997. X        but is intended to be simple to use and follow. I
  1998. X        tried to pretty well do one of everything, to provide
  1999. X        examples.
  2000. X
  2001. XTo Do:
  2002. X        ??
  2003. X
  2004. X--mjr();
  2005. END_OF_FILE
  2006. if test 1953 -ne `wc -c <'b+tree/utils/README'`; then
  2007.     echo shar: \"'b+tree/utils/README'\" unpacked with wrong size!
  2008. fi
  2009. # end of 'b+tree/utils/README'
  2010. fi
  2011. if test -f 'b+tree/utils/btoptim.c' -a "${1}" != "-c" ; then 
  2012.   echo shar: Will not clobber existing file \"'b+tree/utils/btoptim.c'\"
  2013. else
  2014. echo shar: Extracting \"'b+tree/utils/btoptim.c'\" \(3186 characters\)
  2015. sed "s/^X//" >'b+tree/utils/btoptim.c' <<'END_OF_FILE'
  2016. X#include    <stdio.h>
  2017. X#include    <ctype.h>
  2018. X#include    <sys/types.h>
  2019. X#include    <sys/file.h>
  2020. X#include    "btree.h"
  2021. X
  2022. X/*
  2023. X         (C) Copyright, 1988, 1989 Marcus J. Ranum
  2024. X                    All rights reserved
  2025. X
  2026. X
  2027. X          This software, its documentation,  and  supporting
  2028. X          files  are  copyrighted  material  and may only be
  2029. X          distributed in accordance with the terms listed in
  2030. X          the COPYRIGHT document.
  2031. X*/
  2032. X
  2033. X/*
  2034. X    This program optimizes an index by recopying it into a
  2035. X    new one using a reverse load
  2036. X*/
  2037. X
  2038. Xextern    char    *malloc();
  2039. X
  2040. Xmain(ac,av)
  2041. Xint    ac;
  2042. Xchar    *av[];
  2043. X{
  2044. X    BT_INDEX    *old;
  2045. X    BT_INDEX    *new;
  2046. X    char        *infile;
  2047. X    char        *outfile;
  2048. X    int        outpsiz = -1;    /* output page size */
  2049. X    off_t        rrnstore;
  2050. X    int        lenstore;
  2051. X    bt_chrp        bufptr;        /* have to allocate this dynamically */
  2052. X                    /* in case the tree has BIG pages */
  2053. X    int        ret;
  2054. X
  2055. X    for(ret = 1; ret < ac; ret++) {
  2056. X            if(av[ret][0] == '-') 
  2057. X            switch(av[ret][1]) {
  2058. X                case    'p':
  2059. X                    outpsiz = atoi(av[ret + 1]);
  2060. X                    if(outpsiz == 0) {
  2061. X                        (void)fprintf(stderr,"%s: page size must be an integer > 0\n",av[0]);
  2062. X                        outpsiz = -1;
  2063. X                    }
  2064. X                    break;
  2065. X
  2066. X                case    'o':
  2067. X                    outfile = av[ret + 1];
  2068. X                    break;
  2069. X
  2070. X                case    'i':
  2071. X                    infile = av[ret + 1];
  2072. X                    break;
  2073. X
  2074. X                default:
  2075. X                    exit(usage());
  2076. X            }
  2077. X    }
  2078. X
  2079. X    if(outfile == NULL || infile == NULL)
  2080. X        exit(usage());
  2081. X
  2082. X#ifdef    BTOPEN
  2083. X    old = bt_open(infile,O_RDONLY,0600);
  2084. X#else
  2085. X    old = bt_optopen(BT_PATH,    infile,
  2086. X            BT_OMODE,    O_RDONLY,
  2087. X    0);
  2088. X#endif
  2089. X
  2090. X    if(old == NULL) {
  2091. X        perror(infile);
  2092. X        exit(1);
  2093. X    }
  2094. X
  2095. X    /* if output page size was not set on the command line, adopt old */
  2096. X    if(outpsiz == -1)
  2097. X        outpsiz = bt_pagesiz(old);
  2098. X
  2099. X    if((bufptr = (bt_chrp)malloc((unsigned)bt_pagesiz(old))) == NULL) {
  2100. X        perror("cannot allocate buffer memory");
  2101. X        (void)bt_close(old);
  2102. X        exit(1);
  2103. X    }
  2104. X
  2105. X#ifdef    BTOPEN
  2106. X    new = bt_open(av[2],O_CREAT|O_TRUNC,0600);
  2107. X#else
  2108. X    new = bt_optopen(BT_PATH,    outfile,
  2109. X            BT_OMODE,    O_CREAT|O_TRUNC,
  2110. X            BT_OPERM,    0600,
  2111. X            BT_CACHE,    3,
  2112. X            BT_PSIZE,    outpsiz,
  2113. X            BT_CFLAG,    BT_RWCACHE,
  2114. X    0);
  2115. X#endif
  2116. X
  2117. X    if(new == NULL) {
  2118. X        perror(outfile);
  2119. X        exit(1);
  2120. X    }
  2121. X
  2122. X    /* inform the new file we are going to bt_load it */
  2123. X    if(bt_load(new,0,0,0L,BT_BOF)== BT_ERR) {
  2124. X        bt_perror(new,"initialize load");
  2125. X        exit(1);
  2126. X    }
  2127. X
  2128. X    /* since we have not performed any traverses yet, it will start */
  2129. X    /* at the END of the index, automatically - nifty that, ey? */
  2130. X    /* REMEMBER, this HAS to be REVERSE order !!! */
  2131. X    while((ret = bt_traverse(old,BT_BOF,bufptr,bt_pagesiz(old),&lenstore,&rrnstore)) == BT_OK) {
  2132. X        if(bt_load(new,bufptr,lenstore,rrnstore,BT_OK)== BT_ERR) {
  2133. X            bt_perror(new,"bt_load");
  2134. X            exit(1);
  2135. X        }
  2136. X    }
  2137. X    if(ret != BT_BOF) {
  2138. X        (void)fprintf(stderr,"warning: traverse did not complete at BOF!\n");
  2139. X    }
  2140. X
  2141. X    /* a final call to bt_load with BT_EOF tells it to stop */
  2142. X    if(bt_load(new,0,0,0L,BT_EOF) == BT_ERR) {
  2143. X        bt_perror(new,"shut down load");
  2144. X        exit(1);
  2145. X    }
  2146. X
  2147. X    if(bt_close(old) != BT_OK || bt_close(new) != BT_OK) {
  2148. X        (void)fprintf(stderr,"error closing indices\n");
  2149. X        exit(1);
  2150. X    }
  2151. X
  2152. X    (void)free((char *)bufptr);
  2153. X    exit(0);
  2154. X}
  2155. X
  2156. Xusage()
  2157. X{
  2158. X    (void)fprintf(stderr,"usage: btoptim -i input -o output [-p page size]\n");
  2159. X    (void)fprintf(stderr,"where input and output are b+tree indices, and page size a positive integer\n");
  2160. X    return(1);
  2161. X}
  2162. END_OF_FILE
  2163. if test 3186 -ne `wc -c <'b+tree/utils/btoptim.c'`; then
  2164.     echo shar: \"'b+tree/utils/btoptim.c'\" unpacked with wrong size!
  2165. fi
  2166. # end of 'b+tree/utils/btoptim.c'
  2167. fi
  2168. echo shar: End of archive 2 \(of 5\).
  2169. cp /dev/null ark2isdone
  2170. MISSING=""
  2171. for I in 1 2 3 4 5 ; do
  2172.     if test ! -f ark${I}isdone ; then
  2173.     MISSING="${MISSING} ${I}"
  2174.     fi
  2175. done
  2176. if test "${MISSING}" = "" ; then
  2177.     echo You have unpacked all 5 archives.
  2178.     rm -f ark[1-9]isdone
  2179. else
  2180.     echo You still need to unpack the following archives:
  2181.     echo "        " ${MISSING}
  2182. fi
  2183. ##  End of shell archive.
  2184. exit 0
  2185.  
  2186.